<!-- 服务情况能力雷达图 -->
<template>
  <div class="serve-ability-wrapper" :style="wrapperStyle">
    <div ref="chartRef" class="serve-ability-canvas"></div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch, computed } from "vue";
import * as echarts from "echarts";
import { serveAbilityDimensions } from "../constant.js";

const props = defineProps({
  // 雷达图数据，数组格式：[助餐值, 助浴值, 复健运动值, 洗头值, 口部清洁值]
  data: {
    type: Array,
    required: true,
    default: () => [0, 0, 0, 0, 0],
  },
  // 组件尺寸（正方形），默认 300px；传入 0 或负值时占满父容器
  size: {
    type: Number,
    default: 300,
  },
  // 自定义颜色配置
  colors: {
    type: Object,
    default: () => ({
      lineColor: "#409EFF",
      areaColor: "rgba(64, 158, 255, 0.3)",
      pointColor: "#409EFF",
    }),
  },
});

const chartRef = ref(null);
let chartInstance = null;
let resizeObserver = null;
let zrMousemoveHandler = null;
let hoverDimensionIndex = 0; // 根据鼠标角度计算得到的当前维度索引

const wrapperStyle = computed(() => {
  if (props.size && props.size > 0) {
    return { width: props.size + "px", height: props.size + "px" };
  }
  return { width: "100%", height: "100%" };
});

/**
 * 渲染雷达图
 */
const renderChart = () => {
  if (!chartRef.value) return;
  if (!chartInstance) {
    chartInstance = echarts.init(chartRef.value);
  }

  const option = {
    tooltip: {
      trigger: "item",
      position: (pos) => pos,
      formatter: () => {
        const dim = serveAbilityDimensions[hoverDimensionIndex];
        return `标题：${dim.name}<br/>服务单笔数：${dim.value}笔`;
      },
      backgroundColor: "rgba(0, 0, 0, 0.8)",
      borderColor: "transparent",
      textStyle: {
        color: "#fff",
        fontSize: 12,
      },
      padding: [8, 12],
    },
    radar: {
      indicator: serveAbilityDimensions.map((d) => ({
        name: d.name,
        max: d.max,
      })),
      shape: "polygon",
      radius: "63%", // 减小半径为文字留出更多空间
      center: ["50%", "50%"],
      startAngle: 90,
      splitNumber: 5,
      name: {
        textStyle: {
          color: "#666",
          fontSize: 10, // 稍微减小字体大小
        },
        // 增加文字与雷达图的距离，解决"口部清洁"显示不全的问题
        formatter: function (name) {
          return name;
        },
        rich: {
          a: {
            color: "#666",
            fontSize: 11,
            align: "center",
          },
        },
      },
      splitLine: {
        lineStyle: {
          color: "#e6e6e6",
          width: 1,
        },
      },
      splitArea: {
        show: true,
        areaStyle: {
          color: ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"],
        },
      },
      axisLine: {
        lineStyle: {
          color: "#ccc",
        },
      },
    },
    series: [
      {
        type: "radar",
        symbol: "circle",
        symbolSize: 6,
        data: [
          {
            value: serveAbilityDimensions.map((item) => item.value),
            name: "服务能力",
            lineStyle: {
              color: props.colors.lineColor,
              width: 2,
            },
            areaStyle: {
              color: props.colors.areaColor,
            },
            itemStyle: {
              color: props.colors.pointColor,
            },
          },
        ],
      },
    ],
  };

  chartInstance.setOption(option);
};

onMounted(() => {
  renderChart();
  // 跟随容器大小变化响应式调整
  if (chartRef.value && "ResizeObserver" in window) {
    resizeObserver = new ResizeObserver(() => {
      chartInstance && chartInstance.resize();
    });
    resizeObserver.observe(chartRef.value);
  } else {
    window.addEventListener(
      "resize",
      () => chartInstance && chartInstance.resize()
    );
  }

  // 绑定鼠标移动事件：根据鼠标角度映射到相邻区域，显示对应维度的标题与数值
  if (chartInstance) {
    const zr = chartInstance.getZr();
    const n = serveAbilityDimensions.length;
    const startAngle = 90; // 顶部为0度基准（与 radar.startAngle 一致）
    const wedgeAngle = 360 / n;

    zrMousemoveHandler = (e) => {
      try {
        const width = chartInstance.getWidth();
        const height = chartInstance.getHeight();
        const cx = width * 0.5;
        const cy = height * 0.5;
        const x = e.offsetX;
        const y = e.offsetY;

        const dx = x - cx;
        const dy = cy - y; // 上方为正角度
        let deg = (Math.atan2(dy, dx) * 180) / Math.PI; // -180..180
        deg = (deg + 360) % 360; // 0..360，从右侧开始

        const relative = (deg - startAngle + 360) % 360; // 以顶部为0度，顺时针
        const wedgeIndex = Math.floor(relative / wedgeAngle); // 所处相邻区域索引（介于两轴之间）
        const nextIndex = (wedgeIndex + 1) % n; // 显示相邻区域中的后一个维度（满足给定规则）

        hoverDimensionIndex = nextIndex;
        chartInstance.dispatchAction({
          type: "showTip",
          seriesIndex: 0,
          dataIndex: 0,
          position: [x, y],
        });
      } catch (_) {}
    };

    zr.on("mousemove", zrMousemoveHandler);
    zr.on("globalout", () => {
      chartInstance && chartInstance.dispatchAction({ type: "hideTip" });
    });
  }
});

onUnmounted(() => {
  if (resizeObserver) {
    try {
      resizeObserver.disconnect();
    } catch (e) {}
    resizeObserver = null;
  }
  if (chartInstance && zrMousemoveHandler) {
    try {
      chartInstance.getZr().off("mousemove", zrMousemoveHandler);
    } catch (e) {}
    zrMousemoveHandler = null;
  }
  if (chartInstance) {
    chartInstance.dispose();
    chartInstance = null;
  }
});

// 数据变化时更新图表
watch(
  () => [props.data, props.colors],
  () => {
    renderChart();
  },
  { deep: true }
);
</script>

<style scoped lang="scss">
.serve-ability-wrapper {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.serve-ability-canvas {
  width: 100%;
  height: 100%;
}
</style>
